package org.benetech.util;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import org.benetech.event.EventListener;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

public class SafetyNetResolver implements EntityResolver {

	static final Map<String, String> ENTITIES = new HashMap<String, String>();

	static {
		ENTITIES.put("-//NISO//DTD dtbook 2005-2//EN", "entities/dtbook-2005-2.dtd");
		ENTITIES.put("-//NISO//DTD dtbook 2005-2//EN", "entities/dtbook-2005-2.dtd");
		ENTITIES.put("+//ISBN 0-9673008-1-9//DTD OEB 1.2 Package//EN", "entities/oebpkg12.dtd");
		ENTITIES.put("+//ISBN 0-9673008-1-9//DTD OEB 1.0.1 Package//EN", "entities/oebpkg101.dtd");
		ENTITIES.put("+//ISBN 0-9673008-1-9//DTD OEB 1.0 Entities//EN", "entities/oeb1.ent");
		ENTITIES.put("+//ISBN 0-9673008-1-9//DTD OEB 1.0 Entities//EN", "entities/oeb1.ent");
		ENTITIES.put("+//ISBN 0-9673008-1-9//DTD OEB 1.0.1 Document//EN", "entities/oebdoc101.dtd");
		ENTITIES.put("+//ISBN 0-9673008-1-9//DTD OEB 1.2 Entities//EN", "entities/oeb12.ent");
		ENTITIES.put("-//W3C//DTD XHTML 1.0 Strict//EN", "entities/xhtml1-strict.dtd");
		ENTITIES.put("-//W3C//DTD HTML 4.0 Transitional//EN", "entities/xhtml1-transitional.dtd");
		ENTITIES.put("-//W3C//DTD XHTML 1.0 Transitional//EN", "entities/xhtml1-transitional.dtd");
		ENTITIES.put("-//W3C//ENTITIES Latin 1 for XHTML//EN", "entities/xhtml-lat1.ent");
		ENTITIES.put("-//W3C//ENTITIES Symbols for XHTML//EN", "entities/xhtml-symbol.ent");
		ENTITIES.put("-//W3C//ENTITIES Special for XHTML//EN", "entities/xhtml-special.ent");
		ENTITIES.put("+//ISBN 0-9673008-1-9//DTD OEB 1.0 Document//EN", "entities/oebdoc1.dtd");
		ENTITIES.put("+//ISBN//DTD OEB 1.0 Document//EN",  "entities/oebdoc1.dtd");
		ENTITIES.put("-//NISO//DTD dtbook 2005-1//EN", "entities/dtbook-2005-1.dtd");
	}

	private EventListener listener;

	/**
	 * @param listener Accomodates logging.
	 */
	public SafetyNetResolver(final EventListener listener) {
		this.listener = listener;
	}

	/**
	 * Will return null if we want default behavior from the invoking class.
	 * @see EntityResolver#resolveEntity(String, String)
	 * @param publicID
	 * @param systemID
	 * @throws SAXException When bad things happen.
	 * @throws FileNotFoundException
	 */
	public InputSource resolveEntity(final String publicID, final String systemID) throws SAXException, IOException {
		final String resource = ENTITIES.get(publicID);
		if (resource == null) {
			return null;
		}
		final String path = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + resource;
		final Resource[] resources = new PathMatchingResourcePatternResolver().getResources(path);
		for (final Resource next : resources) {
			if (next.exists()) {
				return new InputSource(next.getInputStream());
			}
		}
		this.listener.message("WARN: Failed to find expected DTD/entity file:" + resource);
		return null;
	}

}
